'use client';

import React, { useCallback, useMemo, useRef, useState } from 'react';
import {
  AppstoreOutlined,
  CloudDownloadOutlined,
  CloudUploadOutlined,
  DatabaseOutlined,
  DragOutlined,
  MenuOutlined,
  SortAscendingOutlined,
  SortDescendingOutlined,
  SwapOutlined,
  UnorderedListOutlined,
} from '@ant-design/icons';
import { Dropdown } from 'src/components/Dropdown';
import { TimeAsc, TimeDesc } from 'src/components/Icons';
import { FuncNewImage } from './FuncNewImage';
import { FuncNewFolder } from './FuncNewFolder';
import { Suspense } from 'react';
import { FolderBreadcrumb } from './FolderBreadcrumb';
import { GalleryList } from './GalleryList';
import { Aside, AsideRef } from './Aside';
import { useExplorerInfiniteScroll } from 'src/hooks/useExplorerInfiniteScroll';
import { ChevronLeftIcon, DocumentMagnifyingGlassIcon, MagnifyingGlassIcon, TrashIcon } from '@heroicons/react/24/outline';
import { isTruthy } from 'src/utils';
import clsx from 'clsx';
import { useEventListener, useRequest } from 'ahooks';
import { getFolderInfoById } from 'src/actions/folder';
import { debounce } from 'lodash-es';
import { useAtomValue } from 'jotai';
import { storageSystemOptionsAtom } from 'src/model';
import { useSearchParams } from 'next/navigation';

const defaultPageSize = 10;

const optionsDisplayMode = [
  {
    label: '卡片形式',
    value: 'grid',
    icon: <AppstoreOutlined />,
  },
  {
    label: '列表形式',
    value: 'list',
    icon: <UnorderedListOutlined />,
  },
];

const optionsSortMode = [
  {
    label: '名称降序',
    value: 'name_desc',
    icon: <SortDescendingOutlined />,
  },
  {
    label: '名称升序',
    value: 'name_asc',
    icon: <SortAscendingOutlined />,
  },
  {
    label: '时间降序',
    value: 'time_desc',
    icon: <TimeDesc />,
  },
  {
    label: '时间升序',
    value: 'time_asc',
    icon: <TimeAsc />,
  },
];

function MainNoMemoized() {
  const searchParams = useSearchParams();
  const folderId = searchParams.get('folderId') ?? undefined;
  const defaultDisplayMode = (searchParams.get('displayMode') ?? 'list') as 'grid' | 'list';
  const defaultSortMode = searchParams.get('sortMode') ?? 'time_desc';
  const defaultStorageSystemIds = searchParams.get('storageSystemIds')?.split(',').filter(isTruthy);

  // State
  const [displayMode, setDisplayMode] = useState<'grid' | 'list'>(defaultDisplayMode); // 查看
  const [sortMode, setSortMode] = useState<string>(defaultSortMode); // 排序
  const [storageSystemIds, setStorageSystemIds] = useState<string[] | undefined>(
    defaultStorageSystemIds
  ); // 存储系统
  const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
  const [showAside, setShowAside] = useState(true);
  const [searchLike, setSearchLike] = useState('');
  const storageSystemOptions = useAtomValue(storageSystemOptionsAtom);

  // Refs
  const searchInputRef = useRef<HTMLInputElement>(null);
  const galleryListRef = useRef<HTMLDivElement>(null);
  const asideRef = useRef<AsideRef>(null);

  // Memoized
  const displaySelectedKeys = useMemo(() => [displayMode], [displayMode]);
  const sortSelectedKeys = useMemo(() => [sortMode], [sortMode]);
  const orderBy = useMemo(() => {
    switch (sortMode) {
      case 'name_desc':
        return { fileName: 'desc' as const };
      case 'name_asc':
        return { fileName: 'asc' as const };
      case 'time_desc':
        return { createdAt: 'desc' as const };
      case 'time_asc':
        return { createdAt: 'asc' as const };
      default:
        return { createdAt: 'desc' as const };
    }
  }, [sortMode]);
  const filter = useMemo(() => {
    return { storageSystemIds };
  }, [storageSystemIds]);

  // Requests
  const {
    fetching,
    loadingMore,
    noMore,
    reloadAsync: reloadExplorerList,
    data: explorerList,
  } = useExplorerInfiniteScroll({
    folderId,
    searchLike,
    filter,
    orderBy,
    infiniteScroll: {
      target: galleryListRef,
      pageSize: defaultPageSize,
      threshold: 50,
    },
  });

  const { data: folderInfo, refreshAsync: refreshFolderInfo } = useRequest(
    () => getFolderInfoById(folderId ?? ''),
    {
      debounceWait: 300,
    }
  );

  // Memoized
  const isSearchMode = useMemo(() => {
    return searchLike.trim().length > 0;
  }, [searchLike]);

  const selectedRows = useMemo(() => {
    return selectedRowKeys
      .map((key) => explorerList.find((item) => item.id === key))
      .filter(isTruthy);
  }, [explorerList, selectedRowKeys]);

  const asideTitle = useMemo(() => {
    // 选中单行
    if (selectedRows.length === 1) {
      return selectedRows[0].name;
    }
    // 选中多行
    if (selectedRows.length > 1) {
      return `选中 ${selectedRows.length} 个对象`;
    }
    // 未选中任何行，文件夹下
    if (folderInfo) {
      return folderInfo.name;
    }
    // 未选中任何行，根目录下
    return '属性面板';
  }, [folderInfo, selectedRows]);

  // Handlers
  const handleSelect = useCallback((_selectedRowKeys: string[]) => {
    setSelectedRowKeys(_selectedRowKeys);
  }, []);

  const handleSortChange = useCallback(
    (value: (string | number)[]) => {
      const nextValue = value[0] as string;
      setSortMode(nextValue);
      // 同步更新 URL 查询参数
      // 注意：静默替换地址栏参数，不刷新页面，不能使用 router.push，因为 next.js router 操作会导致页面重新加载，丢失当前状态
      const query = new URLSearchParams(searchParams);
      query.set('sortMode', nextValue);
      window.history.replaceState({}, '', `?${query.toString()}`);
    },
    [searchParams]
  );

  const handleDisplayModeChange = useCallback(
    (value: (string | number)[]) => {
      galleryListRef.current?.scrollTo({ top: 0 });
      const nextValue = value[0] as 'grid' | 'list';
      setDisplayMode(nextValue);
      // 同步更新 URL 查询参数
      const query = new URLSearchParams(searchParams);
      query.set('displayMode', nextValue);
      window.history.replaceState({}, '', `?${query.toString()}`);
    },
    [searchParams]
  );

  const handleStorageSystemIdsChange = useCallback(
    (value: (string | number)[]) => {
      const nextValue = value.length > 0 ? (value as string[]) : undefined;
      setStorageSystemIds(nextValue);
      // 同步更新 URL 查询参数
      const query = new URLSearchParams(searchParams);
      if (nextValue) {
        query.set('storageSystemIds', nextValue.join(','));
      } else {
        query.delete('storageSystemIds');
      }
      window.history.replaceState({}, '', `?${query.toString()}`);
    },
    [searchParams]
  );

  const handleCloseAside = useCallback(() => {
    setShowAside(false);
  }, []);

  const handleRefresh = useCallback(() => {
    reloadExplorerList();
    refreshFolderInfo();
  }, [reloadExplorerList, refreshFolderInfo]);

  const handleSearchInputFocus = useCallback(() => {
    searchInputRef.current?.select();
    searchInputRef.current?.focus();
  }, []);

  const handleSearchInputChange = useMemo(
    () =>
      debounce((event: React.ChangeEvent<HTMLInputElement>) => {
        const value = event.target.value.trim();
        // 清除选中状态
        setSelectedRowKeys([]);
        // 更新搜索关键字
        setSearchLike(value);
      }, 500),
    []
  );

  // Memoized
  const selectedToolbar = useMemo(
    () => [
      {
        label: selectedRowKeys.length > 1 ? '批量删除' : '删除',
        value: 'delete',
        icon: <TrashIcon className="size-4" />,
        className: 'btn-error',
        onClick: () => {},
      },
      {
        label: selectedRowKeys.length > 1 ? '打包下载' : '下载',
        value: 'download',
        icon: <CloudDownloadOutlined className="text-base" />,
      },
      {
        label: '移动',
        value: 'move',
        icon: <DragOutlined className="text-base" />,
      },
    ],
    [selectedRowKeys.length]
  );

  // Event Listeners
  useEventListener('keydown', (event) => {
    // Ctrl + K 快捷键触发搜索
    if (event.ctrlKey && event.key === 'k') {
      event.preventDefault();
      if (searchInputRef.current) {
        searchInputRef.current.focus();
      }
    }
    // Ctrl + A 快捷键全选
    if (event.ctrlKey && event.key === 'a') {
      event.preventDefault();
      setSelectedRowKeys(explorerList.map((item) => item.id));
    }
    // Ctrl + D 快捷键取消全选
    if (event.ctrlKey && event.key === 'd') {
      event.preventDefault();
      setSelectedRowKeys([]);
    }
    // Ctrl + R 快捷键刷新
    if (event.ctrlKey && event.key === 'r') {
      event.preventDefault();
      handleRefresh();
    }
    // Ctrl + Alt + B 快捷键切换属性面板
    if (event.ctrlKey && event.altKey && event.key === 'b') {
      event.preventDefault();
      setShowAside((prev) => !prev);
    }
    // Ctrl + Alt + M 快捷键切换显示模式
    if (event.ctrlKey && event.altKey && event.key === 'm') {
      event.preventDefault();
      setDisplayMode((prev) => (prev === 'grid' ? 'list' : 'grid'));
    }
    // Ctrl + Alt + P 预览选中图片
    if (event.ctrlKey && event.altKey && event.key === 'p') {
      event.preventDefault();
      if (selectedRows.length > 0 && asideRef.current) {
        asideRef.current.previewPhotos();
      }
    }
  });

  return (
    <div className="absolute inset-0 size-full flex flex-col overflow-hidden">
      <header className="flex-none h-12 px-5 flex items-center justify-between gap-5">
        <h1 className="text-xl font-bold text-purple-800 dark:text-purple-50">我的图库</h1>
        <div className="flex items-center gap-5">
          <div className="flex items-center gap-1">
            <label className="input border-gray-200 dark:border-neutral-700 !outline-0 rounded-full w-64">
              <MagnifyingGlassIcon className="size-6" />
              <input
                ref={searchInputRef}
                type="search"
                placeholder="搜索图片"
                onFocus={handleSearchInputFocus}
                onChange={handleSearchInputChange}
              />
              <kbd className="kbd kbd-sm">Ctrl</kbd>
              <kbd className="kbd kbd-sm">K</kbd>
            </label>
          </div>
          <button type="button" className="btn btn-primary rounded-full" title="上传图片（支持文件夹批量上传）">
            <CloudUploadOutlined />
            上传图片
          </button>
        </div>
      </header>
      <main aria-label="body" className="flex-auto h-full mt-5 flex overflow-hidden">
        <main className="flex-auto flex flex-col h-full overflow-hidden">
          <div
            aria-label="toolbar"
            className="flex-none flex items-center justify-between h-12 px-5 border-y border-gray-200 dark:border-neutral-700"
          >
            <div className="flex-1 flex items-center gap-2 overflow-hidden">
              {isSearchMode ? (
                <div className="flex items-center gap-2">
                  <DocumentMagnifyingGlassIcon className="size-5 text-primary" />
                  <span className="text-sm font-bold">搜索结果</span>
                </div>
              ) : (
                <Suspense>
                  <FolderBreadcrumb />
                  <FuncNewFolder onSuccess={reloadExplorerList} />
                  <FuncNewImage onSuccess={handleRefresh} />
                </Suspense>
              )}
              {selectedRowKeys.length > 0 && (
                <>
                  <div
                    aria-label="divider"
                    className="mx-5 w-[1px] h-5 bg-gray-200 dark:bg-neutral-700"
                  />
                  {selectedToolbar.map((item) => (
                    <button
                      key={item.value}
                      type="button"
                      className={clsx('btn btn-sm btn-ghost rounded-full', item.className)}
                    >
                      {item.icon}
                      {item.label}
                    </button>
                  ))}
                </>
              )}
            </div>
            <div className="w-[350px] flex items-center justify-end gap-2 overflow-hidden">
              <Dropdown
                className="btn btn-sm btn-ghost rounded-full"
                selectedKeys={storageSystemIds}
                onSelect={handleStorageSystemIdsChange}
                checkable
                options={storageSystemOptions}
              >
                <DatabaseOutlined />
                存储系统
              </Dropdown>
              <Dropdown
                className="btn btn-sm btn-ghost rounded-full"
                selectedKeys={displaySelectedKeys}
                singleMode
                checkable
                autoClose
                showCheckIcon
                options={optionsDisplayMode}
                onSelect={handleDisplayModeChange}
              >
                <MenuOutlined />
                查看
              </Dropdown>
              <Dropdown
                className="btn btn-sm btn-ghost rounded-full"
                selectedKeys={sortSelectedKeys}
                singleMode
                checkable
                autoClose
                showCheckIcon
                options={optionsSortMode}
                onSelect={handleSortChange}
              >
                <SwapOutlined rotate={90} />
                排序
              </Dropdown>
              {!showAside && (
                <button
                  type="button"
                  className="btn btn-sm btn-ghost rounded-full"
                  title="属性面板"
                  onClick={() => {
                    setShowAside((prev) => !prev);
                  }}
                >
                  <ChevronLeftIcon className="size-4" />
                  属性面板
                </button>
              )}
            </div>
          </div>
          <div aria-label="content" className="flex-auto bg-base-100 overflow-hidden">
            <GalleryList
              ref={galleryListRef}
              className="size-full"
              isSearchMode={isSearchMode}
              loading={fetching}
              loadingMore={loadingMore}
              noMore={noMore && explorerList.length > defaultPageSize}
              dataSource={explorerList}
              mode={displayMode}
              selectedKeys={selectedRowKeys}
              onSelect={handleSelect}
            />
          </div>
        </main>
        <Aside
          ref={asideRef}
          title={asideTitle}
          selectedRows={selectedRows}
          visible={showAside}
          folderInfo={folderInfo}
          onClose={handleCloseAside}
        />
      </main>
    </div>
  );
}

export const Main = React.memo(MainNoMemoized);
